﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GamePlugin.Logics.Core
{
    public class HierarchyStateMachine
    {
        private Dictionary<string, MachineState> _States = new Dictionary<string, MachineState>();

        public int ChildrenStateCount
        {
            get
            {
                return _States.Count;
            }
        }

        public void Reset()
        {
            this._CurrentState = null;

            foreach (MachineState state in _States.Values)
            {
                state.Reset();
            }
        }

        public bool IsNeedReset
        {
            get;
            set;
        }

        private MachineState _CurrentState;

        public void AddState(string name)
        {
            _States.Add(name, new MachineState(this, name));
        }

        public void AddState(string name, MachineState state)
        {
            _States.Add(name, state);
            state.StateName = name;
            state.Owner = this;
        }

        public string DefaultState
        {
            get;
            set;
        }

        public string CurrentState
        {
            get
            {
                return _CurrentState.StateName;
            }
            set
            {
                _CurrentState = _States[value];
                if (_CurrentState == null)
                    throw new Exception("Machine state is null");
            }
        }

        public MachineState this[string behaviorName]
        {
            get
            {
                return this._States[behaviorName];
            }
            set
            {
                _States[behaviorName] = value;
            }
        }

        public void ChangeToState(string name, bool overlap = false)
        {
            if (_CurrentState == null ||
                _CurrentState.StateName == name && overlap == true ||
                _CurrentState.StateName != name)
            {
                if (_CurrentState != null)
                    _CurrentState.Terminate(null);
                this.CurrentState = name;
                if (this._CurrentState.DefaultState != null && this._CurrentState.DefaultState.Length > 0)
                    this._CurrentState.CurrentState = this._CurrentState.DefaultState;
                if (_CurrentState != null)
                    _CurrentState.Start(null);
                if (_CurrentState == null)
                    throw new Exception("Machine state is null");
            }
        }

        public void Startup(GameTime gameTime)
        {
            if (_States == null)
                _States = new Dictionary<string, MachineState>();
            _States.Clear();
        }

        public virtual void Update(GameTime gameTime)
        {
            if (this.IsNeedReset == true)
            {
                this.Reset();
                this.IsNeedReset = false;
            }

            if (_States == null)
                _States = new Dictionary<string, MachineState>();

            if (_CurrentState == null && DefaultState != null && DefaultState.Length > 0)
                this.ChangeToState(DefaultState);

            foreach (MachineState state in _States.Values)
            {
                if (state != null && state == _CurrentState)
                {
                    state.Update(gameTime);
                    break;
                }
            }
        }
    }
}
